package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.domain.R;
import com.piggy.common.core.utils.FeignResultUtils;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.bo.*;
import com.piggy.logi.sys.domain.LogiProject;
import com.piggy.logi.sys.mapper.LogiProjectMapper;
import com.piggy.logi.sys.service.*;
import com.piggy.logi.sys.vo.*;
import com.piggy.sys.api.RemoteDistrictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 项目管理Service业务层处理
 *
 * @author piggy
 * @date 2023-08-18
 */
@Slf4j
@Service
public class LogiProjectServiceImpl extends ServiceImpl<LogiProjectMapper, LogiProject> implements ILogiProjectService {

    @Resource
    private ILogiProjectShipService shipService;

    @Resource
    private ILogiProjectBranchService branchService;

    @Resource
    private ILogiProjectShipLineService shipLineService;

    @Resource
    private ILogiProjectCarrierService carrierService;

    @Resource
    private RemoteDistrictService districtService;

    @Resource
    private ILogiCustomerService customerService;

    @Override
    public LogiProjectExtVo queryById(Long id) {
        LogiProjectExtVo vo = getVoById(id, LogiProjectExtVo.class);
        if (ObjectUtil.isEmpty(vo)) {
            return vo;
        }
        return fillData(Lists.newArrayList(vo)).get(0);

    }

    @Override
    public TableDataInfo<LogiProjectExtVo> queryPageList(LogiProjectQueryBo bo) {
        bo.setDeptId(SecurityUtils.getDeptId());
        PagePlus<LogiProject, LogiProjectExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiProjectExtVo.class);
        result.setRecordsVo(fillData(result.getRecordsVo()));
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<LogiProjectExtVo> queryList(LogiProjectQueryBo bo) {
        bo.setDeptId(SecurityUtils.getDeptId());
        return fillData(listVo(buildQueryWrapper(bo), LogiProjectExtVo.class));
    }

    private LambdaQueryWrapper<LogiProject> buildQueryWrapper(LogiProjectQueryBo bo) {
        LambdaQueryWrapper<LogiProject> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getId() != null, LogiProject::getId, bo.getId());
        lqw.like(StrUtil.isNotBlank(bo.getProjectName()), LogiProject::getProjectName, bo.getProjectName());
        lqw.eq(StrUtil.isNotBlank(bo.getLeader()), LogiProject::getLeader, bo.getLeader());
        lqw.eq(StrUtil.isNotBlank(bo.getPhone()), LogiProject::getPhone, bo.getPhone());
        lqw.eq(bo.getDistrictId() != null, LogiProject::getDistrictId, bo.getDistrictId());
        lqw.eq(StrUtil.isNotBlank(bo.getAddress()), LogiProject::getAddress, bo.getAddress());
        lqw.eq(bo.getBeginDate() != null, LogiProject::getBeginDate, bo.getBeginDate());
        lqw.eq(bo.getEndDate() != null, LogiProject::getEndDate, bo.getEndDate());
        lqw.eq(StrUtil.isNotBlank(bo.getSettleType()), LogiProject::getSettleType, bo.getSettleType());
        lqw.eq(StrUtil.isNotBlank(bo.getAttachInfo()), LogiProject::getAttachInfo, bo.getAttachInfo());
        lqw.eq(bo.getSpotPay() != null, LogiProject::getSpotPay, bo.getSpotPay());
        lqw.eq(bo.getFreightPay() != null, LogiProject::getFreightPay, bo.getFreightPay());
        lqw.eq(bo.getArrearsPay() != null, LogiProject::getArrearsPay, bo.getArrearsPay());
        lqw.eq(bo.getReceiptPay() != null, LogiProject::getReceiptPay, bo.getReceiptPay());
        lqw.eq(bo.getMonthlyBalance() != null, LogiProject::getMonthlyBalance, bo.getMonthlyBalance());
        lqw.eq(bo.getMonthlyDays() != null, LogiProject::getMonthlyDays, bo.getMonthlyDays());
        // 部门数据权限过滤
        if (ObjectUtil.isNotNull(bo.getDeptId())) {
            SqlUtil.dataPermissionFilter(lqw, bo.getDeptId());
        }
        return lqw;
    }

    public List<LogiProjectExtVo> fillData(List<LogiProjectExtVo> extVos) {

        List<Long> customerIds = extVos.stream().map(LogiProjectExtVo::getCustomerId).distinct().collect(Collectors.toList());
        customerIds.add(-1L);

        List<LogiCustomerExtVo> customerList = customerService.queryList(new LogiCustomerQueryBo().setCustomerIdList(customerIds));
        LinkedHashMap<Long, LogiCustomerExtVo> customerMap = customerList.stream().collect(LinkedHashMap::new, (m, v) -> m.put(v.getCustomerId(), v), LinkedHashMap::putAll);

        extVos.stream().peek(Any-> Any.setCustomer(customerMap.get(Any.getCustomerId()))).collect(Collectors.toList());

        List<Long> projectIds = extVos.stream().map(LogiProjectExtVo::getId).distinct().collect(Collectors.toList());
        projectIds.add(-1L);

        List<String> distIds = extVos.stream().map(vo-> ObjectUtil.defaultIfNull(vo.getDistrictId(),0L).toString()).distinct().collect(Collectors.toList());
        distIds.add("-1");

        R<Map<String, String>> distNameMap =  districtService.getDistrictMap(distIds, SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(distNameMap);

        LinkedHashMap<Long, LogiProjectExtVo> projectMap = extVos.stream().collect(LinkedHashMap::new, (m, v) -> m.put(v.getId(), v), LinkedHashMap::putAll);

        List<LogiProjectShipExtVo> shipList = shipService.queryList(new LogiProjectShipQueryBo().setProjectIdList(projectIds));
        List<LogiProjectBranchExtVo> brandList = branchService.queryList(new LogiProjectBranchQueryBo().setProjectIdList(projectIds));
        List<LogiProjectCarrierExtVo> carrierList = carrierService.queryList(new LogiProjectCarrierQueryBo().setProjectIdList(projectIds));
        List<LogiProjectShipLineExtVo> shipLineList = shipLineService.queryList(new LogiProjectShipLineQueryBo().setProjectIdList(projectIds));

        shipList.stream().peek(Any-> projectMap.get(Any.getProjectId()).getShipList().add(Any)).collect(Collectors.toList());

        shipLineList.stream().peek(Any-> projectMap.get(Any.getProjectId()).getShipLineList().add(Any)).collect(Collectors.toList());

        brandList.stream().peek(Any-> projectMap.get(Any.getProjectId()).getBranchList().add(Any)).collect(Collectors.toList());

        carrierList.stream().peek(Any-> projectMap.get(Any.getProjectId()).getCarrierList().add(Any)).collect(Collectors.toList());

        extVos.stream().peek(Any-> projectMap.get(Any.getId()).setDistrictName(distNameMap.getData().get(Any.getDistrictId()+""))).collect(Collectors.toList());

        return Lists.newArrayList(projectMap.values());
    }

    @Override
    public Boolean insertByAddBo(LogiProjectExtEditBo bo) {
        LogiProject add = BeanUtil.toBean(bo, LogiProject.class);
        boolean ret = save(add);
        // 处理项目配置
        batchAddOther((LogiProjectExtEditBo) bo.setId(add.getId()));
        return ret;
    }

    @Override
    public Boolean updateByEditBo(LogiProjectExtEditBo bo) {
        LogiProject update = BeanUtil.toBean(bo, LogiProject.class);
        boolean ret = updateById(update);
        // 处理项目配置
        batchUpdateOther((LogiProjectExtEditBo) bo.setId(update.getId()));
        return ret;
    }

    private void batchAddOther(LogiProjectExtEditBo bo) {
        bo.getBranchList().stream().peek(Any-> Any.setProjectId(bo.getId())).collect(Collectors.toList());
        bo.getCarrierList().stream().peek(Any-> Any.setProjectId(bo.getId())).collect(Collectors.toList());
        bo.getShipList().stream().peek(Any-> Any.setProjectId(bo.getId())).collect(Collectors.toList());
        bo.getShipLineList().stream().peek(Any-> {
            Any.setProjectId(bo.getId());
            Any.setProjectName(bo.getProjectName());
        }).collect(Collectors.toList());
        shipService.batchByAddBo(bo.getShipList());
        shipLineService.batchByAddBo(bo.getShipLineList());
        branchService.batchByAddBo(bo.getBranchList());
        carrierService.batchByAddBo(bo.getCarrierList());
    }

    private void batchUpdateOther(LogiProjectExtEditBo bo) {
        bo.getBranchList().stream().peek(Any-> Any.setProjectId(bo.getId())).collect(Collectors.toList());
        bo.getCarrierList().stream().peek(Any-> Any.setProjectId(bo.getId())).collect(Collectors.toList());
        bo.getShipList().stream().peek(Any-> Any.setProjectId(bo.getId())).collect(Collectors.toList());
        bo.getShipLineList().stream().peek(Any-> {
            Any.setProjectId(bo.getId());
            Any.setProjectName(bo.getProjectName());
        }).collect(Collectors.toList());
        shipService.batchByUpdateBo(bo.getShipList());
        shipLineService.batchByUpdateBo(bo.getShipLineList());
        branchService.batchByUpdateBo(bo.getBranchList());
        carrierService.batchByUpdateBo(bo.getCarrierList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
